'''
Created on 2010/09/09

@author: yukiyonezawa
'''
from pyrfid.asn1.Encoder import Encoder
from pyrfid.DataProtocol.DSFID.DataFormat.DataFormatUtil import DataFormatUtil
from pyrfid.DataProtocol.DSFID.DataFormat.RootOIDEncoded import RootOIDEncoded
from pyrfid.DataProtocol.DSFID.Processor.Decompactor import Decompactor
from pyrfid.DataProtocol.AddObject import AddObject
from pyrfid.Util.Util import Util
from pyrfid.DataProtocol.LogicalMemory.DataSet import DataSet
from pyrfid.DataProtocol.DSFID.Processor.Compactor import Compactor

class RelatedRootOID(object):
    
    DATA_FORMAT_ID_MIN = 3
    DATA_FORMAT_ID_MAX = 29
        
    ISO_15434 = "1 0 15434"
    ISO_6523 = "1 0 6523" 
    ISO_15459 = "1 0 15459"
    LIBRARY_LOAN_ITEMS = "1 0 15961 6"
    ISO_15962_COMBINED = "1 0 15961"
    DATA_IDENTIFIER_ALGORITHM ="1 0 15961 10"
    IATA_BAGGAGE = "1 0 15961 12"
    
    #this is test code
    ISO_15961_9 = "1 0 15961 9"
    
    ROOT_OID = ""    
    ROOT_OID_LIST = {"3":ISO_15434, "4":ISO_6523, "5":ISO_15459, "6":LIBRARY_LOAN_ITEMS, "8":ISO_15962_COMBINED, "10":DATA_IDENTIFIER_ALGORITHM, "12":IATA_BAGGAGE, "9":ISO_15961_9}
    
    def __init__(self, data_format_id):
        """
        data_format_id -- a int data
        """
        print data_format_id
        print self.ROOT_OID_LIST.has_key(str(data_format_id))                
        if self.ROOT_OID_LIST.has_key(str(data_format_id)) == True:        
            self.ROOT_OID = self.ROOT_OID_LIST.get(str(data_format_id))
        else:
            raise 'Indicated Data Format ID is not defined'        
        self.DATA_FORMAT_ID = data_format_id    
    
    def formattingDataSet(self, existing_data_set_list, add_data_set_list):
        
        encoded_root_OID = Encoder.oidEncode(RelatedRootOID.ROOT_OID_LIST[str(self.DATA_FORMAT_ID)])        
        add_data_set_list = self.__rootOIDFormat(add_data_set_list, encoded_root_OID)        
        add_data_set_list = self.encodeLengthOfIdentifier(add_data_set_list)
        
        return_add_data_set_list = list()

#        if isNewAddDataSet == True:
#            data_set = DataSet()
#            data_set.OBJECT_IDENTIFIER = encoded_root_OID
#            precursor = Util.convertIntToBit(len(encoded_root_OID) / 2, 7)
#            data_set.PRECURSOR =  "0" + precursor
#            data_set.LENGTH_OF_OBJECT = "00"
#            return_add_data_set_list.append(data_set)
        
        for data_set in existing_data_set_list:
            return_add_data_set_list.append(data_set)
        
        for data_set in add_data_set_list:
            return_add_data_set_list.append(data_set)
        
        return return_add_data_set_list
    
        
    def encodeLengthOfIdentifier(self, data_set_list):
        
        result_data_set_list = []
        for data_set in data_set_list:
            
            int_related_oid = int(data_set.OBJECT_IDENTIFIER, 16)
            if int_related_oid >= 1 and int_related_oid <= 14 and data_set.OFFSET == "":
                #include related OID in Precursor 
                data_set.PRECURSOR = data_set.PRECURSOR[:4] + Util.convertHexToBit(data_set.OBJECT_IDENTIFIER)[4:]
                data_set.OBJECT_IDENTIFIER = ""
                
            elif int_related_oid >= 1 and int_related_oid <= 14 and data_set.OFFSET != "":
                #include related OID in Precursor 
                raise NotImplementedError()
            
            elif int_related_oid >= 15 and int_related_oid <= 127 and data_set.OFFSET == "":
                data_set.PRECURSOR = data_set.PRECURSOR[:4] + "1111"
                data_set.OBJECT_IDENTIFIER = Util.convertIntToHex(int_related_oid - 15, 2)
                
            elif int_related_oid >= 15 and int_related_oid <= 127 and data_set.OFFSET != "":
                raise NotImplementedError()
            
            elif data_set.OFFSET == "":
                data_set.PRECURSOR = data_set.PRECURSOR[:4] + '1111'
                length_of_object_identifier = len(data_set.OBJECT_IDENTIFIER) / 2
                if length_of_object_identifier >= 1 and length_of_object_identifier <= 16:
                    lenHex = Util.convertBitToHex('100' + Util.convertIntToBit(length_of_object_identifier + 1).zfill(5))
                    data_set.LENGTH_OF_OBJECT_IDENTIFIER = lenHex
                elif length_of_object_identifier >= 17 and length_of_object_identifier <= 126:
                    lenHex = "A0" + Util.convertIntToHex(length_of_object_identifier, 2)
                    data_set.LENGTH_OF_OBJECT_IDENTIFIER  = lenHex
            
            elif data_set.OFFSET != "":
                pass
            
            else:
                raise "ERROR"
            data_set.showDataSet()
            
            result_data_set_list.append(data_set)
        return result_data_set_list
        

    def __rootOIDFormat(self, add_data_set_list, encoded_root_OID):
        
        for data_set in add_data_set_list:
            print encoded_root_OID
            print data_set.OBJECT_IDENTIFIER[:len(encoded_root_OID)]
            if encoded_root_OID != data_set.OBJECT_IDENTIFIER[:len(encoded_root_OID)]:
                raise " A OBJECT IDETNFIER does not match Root "
            data_set.OBJECT_IDENTIFIER = data_set.OBJECT_IDENTIFIER[len(encoded_root_OID):]
        return add_data_set_list
    
    def __getRootOID(self, add_data_set_list):
        """docstring for getRootOid"""
        print add_data_set_list
        
        minLength = len(add_data_set_list[0].OBJECT_IDENTIFIER)
        if len(add_data_set_list) <= 1:
            return ""
        
        for index in range(1, len(add_data_set_list)):
            tempMinLength = len(add_data_set_list[index].OBJECT_IDENTIFIER)
            if minLength > tempMinLength:
                minLength = tempMinLength
        
        sameOfobjectIdentifierIndex = 0
    
        for objectIdentifierIndex in range(1, minLength / 2):
            value = add_data_set_list[0].OBJECT_IDENTIFIER[:objectIdentifierIndex*2]
            same = True
            for index in range(1, len(add_data_set_list)):
                if value != add_data_set_list[index].OBJECT_IDENTIFIER[:objectIdentifierIndex*2]:
                    same = False
            if same == True:
                sameOfobjectIdentifierIndex += 1
    
        rootOID = add_data_set_list[0].OBJECT_IDENTIFIER[:sameOfobjectIdentifierIndex*2]        
        return rootOID
    
    def decodeDataSetToAddData(self, data_set_list):
        
        add_objects_list = []
        for data_set in data_set_list:
            suffix_object_identifier = ""
            if data_set.OBJECT_IDENTIFIER != "":                
                #ref D.4.3.2
                suffix_object_identifier = Util.convertIntToHex(int(data_set.OBJECT_IDENTIFIER, 16) + 15)
            else:
                suffix_object_identifier = str(int(data_set.PRECURSOR[4:], 2))
            
            encoded_object_identifier = Encoder.oidEncode(RootOIDEncoded.ROOT_OID_LIST[str(self.DATA_FORMAT_ID)]) + suffix_object_identifier.zfill(2)
            
            object_compaction_type = data_set.getCompactionType()
            object_value = Decompactor.decompactObject(object_compaction_type, data_set.OBJECT)
            add_objects_list.append(AddObject(encoded_object_identifier, False, object_value, AddObject.COMPACT, False))
        
        return add_objects_list
        